package com.nulldev.util.web.YouTubeExtractor.trending;

import static com.nulldev.util.web.YouTubeExtractor.YouTubeExtractorConstants.CLIENT_VERSION;
import static com.nulldev.util.web.YouTubeExtractor.YouTubeExtractorConstants.PAGE_CL;
import static com.nulldev.util.web.YouTubeExtractor.YouTubeExtractorConstants.PAGE_LABEL;
import static com.nulldev.util.web.YouTubeExtractor.YouTubeExtractorConstants.PAGE_STS;
import static com.nulldev.util.web.YouTubeExtractor.YouTubeExtractorConstants.UTC_OFFSET;
import static com.nulldev.util.web.YouTubeExtractor.YouTubeExtractorConstants.VARIANTS_CHECKSUM;
import static com.nulldev.util.web.YouTubeExtractor.util.YouTubeExtractorUtil.getYTString;

import java.util.List;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.data.Arrays.arrays.FastLists;
import com.nulldev.util.languages.json.uniapi.UniJsonIterableValue;
import com.nulldev.util.languages.json.uniapi.UniJsonValue;
import com.nulldev.util.web.HttpClient.HttpClient;
import com.nulldev.util.web.HttpClient.HttpResponse;
import com.nulldev.util.web.URLUtils.Entry;
import com.nulldev.util.web.YouTubeExtractor.YouTubeExtractor;

public class YouTubeTrending {
	public static final String NEW_API_URL = "https://www.youtube.com/feed/trending?pbj=1";

	public static class TrendingEntry {
		public final String videoID;
		public final String durationText;
		public final String title;
		public final boolean isVerified;
		public final String animated_img_url;
		public final String channelName;
		public final String channelLink;

		public TrendingEntry(final String videoID, final String durationText, final String title, final boolean isVerified, final String animated_img_url,
				final String channelName, final String channelLink) {
			this.videoID = videoID;
			this.durationText = durationText;
			this.title = title;
			this.isVerified = isVerified;
			this.animated_img_url = animated_img_url;
			this.channelName = channelName;
			this.channelLink = channelLink;
		}

		public String url() {
			return "/watch?v=" + this.videoID;
		}

	}

	public static List<TrendingEntry> getTrending() throws Exception {
		return getTrending(true);
	}

	private static final Entry[] es = new Entry[]
		{ new Entry("X-YouTube-Client-Name", "1"), new Entry("X-YouTube-Client-Version", CLIENT_VERSION), new Entry("X-YouTube-Page-CL", PAGE_CL),
				new Entry("X-YouTube-Page-Label", PAGE_LABEL), new Entry("X-YouTube-STS", PAGE_STS), new Entry("X-YouTube-Utc-Offset", UTC_OFFSET),
				new Entry("X-YouTube-Variants-Checksum", VARIANTS_CHECKSUM) };

	public static List<TrendingEntry> getTrending(final boolean sendConsentCookie) throws Exception {
		final HttpResponse<String> o = HttpClient.getString().url(NEW_API_URL).headers(es)
				.headers(sendConsentCookie ? YouTubeExtractor.DEFAULT_COOKIES : YouTubeExtractor.BLANK_COOKIES).create();
		final String d = o.dataThenClose();
		final UniJsonValue n;
		final boolean is_array;
		if (d.startsWith("[") && d.endsWith("]")) {
			n = UniJsonValue.parseArray(d);
			is_array = true;
		} else {
			n = UniJsonValue.parse(d);
			is_array = false;
		}
		final UniJsonValue co = is_array ? n.getJsonObject(1) : n;
		final UniJsonValue response = co.get("response").get("contents").get("twoColumnBrowseResultsRenderer").get("tabs").asArray().get(0).get("tabRenderer");
		final UniJsonIterableValue contents = response.get("content").get("sectionListRenderer").get("contents").asArray();
		final UniJsonIterableValue primary_trending = contents.get(1).get("itemSectionRenderer").arrayGet("contents").get(0).get("shelfRenderer").get("content")
				.get("expandedShelfContentsRenderer").arrayGet("items").asArray();
		final List<TrendingEntry> tes = FastLists.list(50);
		for (final UniJsonValue _u : primary_trending) {
			final UniJsonValue u = _u.get("videoRenderer");
			final String vid = u.getString("videoId");
			final String dt = getYTString(u.get("lengthText"));
			String title = "";
			for (final UniJsonValue _v : u.get("title").get("runs").asArray()) {
				title += _v.getString("text");
			}
			boolean isVerified = false;
			try {
				if (u.hasValue("ownerBadges")) {
					for (final UniJsonValue badge : u.get("ownerBadges").asArray()) {
						isVerified = badge.get("metadataBadgeRenderer").getString("style").equalsIgnoreCase("BADGE_STYLE_TYPE_VERIFIED");
						if (isVerified) {
							break;
						}
					}
				}
			} catch (Exception e) {
				JVM.errorln(e);
			}
			String animated_img_url = null;
			try {
				if (u.hasValue("richThumbnail")) {
					animated_img_url = u.get("richThumbnail").get("movingThumbnailRenderer").get("movingThumbnailDetails").get("thumbnails").asArray().last()
							.getString("url");
				}
			} catch (Exception e) {
				JVM.errorln(e);
			}
			final String channelName = getYTString(u.get("ownerText"));
			final String channelLink = u.get("ownerText").get("runs").asArray().get(0).get("navigationEndpoint").get("browseEndpoint").getString("browseId");
			tes.add(new TrendingEntry(vid, dt, title, isVerified, animated_img_url, channelName, channelLink));
		}
		return tes;
	}

	public static void main(String[] args) throws Exception {
		try {
			getTrending();
		} catch (Exception e) {
			JVM.errorln(e);
		}
	}
}
